package godb

import (
	"database/sql"
	"math"
	"time"
)

// TransactionFunc 事务回调函数
type TransactionFunc func(tx TxSQL) error

// SQL 数据库操作接口
type SQL interface {
	Query
	// DataBaseName 数据库名称
	DataBaseName() string
	// SetMaxOpenConns 设置最大连接数
	SetMaxOpenConns(n int)
	// SetMaxIdleConns 设置最大空闲连接数
	SetMaxIdleConns(n int)
	// SetConnMaxIdleTime 设置最大空闲连接时间,超时后将关闭连接
	SetConnMaxIdleTime(n time.Duration)
	// GetDb 获取数据库对象
	GetDb() (*sql.DB, error)
	// SetQueryTimeOut 设置查询超时时间
	SetQueryTimeOut(outTime time.Duration)
	// Transaction 事务处理
	//
	// param t TransactionFunc 事务处理函数
	//
	// param new bool 是否创建新事物,默认false,如果设置true不管事务是否存在都会创建新事物
	Transaction(t TransactionFunc, option ...*sql.TxOptions) error
	// Close 关闭数据库
	Close()
}

// TxSQL 事物数据操作接口
type TxSQL interface {
	Query
	//GetTx 获取事务对象
	GetTx() *sql.Tx
}

type TxSQLErr interface {
	// Err 事务错误
	Err() error
}

// Query 查询操作集合
type Query interface {
	// QueryRows 查询多条数据,结果以[]map[string]interface{}方式返回
	// 返回结果,使用本package中的类型函数进行数据解析
	//
	// param sql string SQL
	//
	// param args... interface{} SQL参数
	QueryRows(sql string, args ...interface{}) *QueryResult
	// QueryRow 查询多条数据,结果以[]map[string]interface{}方式返回
	// 返回结果,使用本package中的类型函数进行数据解析
	//
	// param sql string SQL
	//
	// param args... interface{} SQL参数
	QueryRow(sql string, args ...interface{}) *QueryResult
	// Exec 执行一条SQL
	//
	// param sql string SQL
	//
	// param args... interface{} SQL参数
	Exec(sql string, args ...interface{}) *ExecResult
	// QueryWithPage 分页查询SQL
	//
	// 返回结果,使用本package中的类型函数进行数据解析
	//
	// param sql string SQL
	//
	// param page *PageObj 分页数据
	//
	// param args... interface{} SQL参数
	QueryWithPage(sql string, page *PageObj, args ...interface{}) *QueryResult
	// Prepare 预处理
	Prepare(query string) (*sql.Stmt, error)
}

// RowIterator 行读取游标
type RowIterator interface {
	// HasNext 是否有下一条记录
	HasNext() bool
	// Reset 重置游标到首位
	Reset()
	// Next 获取下一条数据
	Next() (map[string]interface{}, error)
	// Length 总数据数
	Length() int
}

// PageObj 分页数据
type PageObj struct {
	Page     int   `json:"page"`
	Rows     int   `json:"rows"`
	Total    int64 `json:"total"`
	PageSize int   `json:"allpage"`
}

// SetTotal 设置分页
func (p *PageObj) SetTotal(total int64) {
	if p.Rows < 1 { //如果未设置分页,自动设置成20
		p.Rows = 20
	}
	p.Total = total
	p.PageSize = int(math.Ceil(float64(total) / float64(p.Rows)))
}
